<template>
    <div class="d3graph-container" ref="d3Container">
        <div id="3d-graph" class="three-graph"></div>
        <div id="info" v-show="selectNodeData.name !== undefined">
            <el-card class="node-card">
                <!--                <div slot="header" class="clearfix">-->
                <!--                    <span>{{ selectNodeData.name }}</span>-->
                <!--                </div>-->
                <!--                <div v-for="(item, key) in selectNodeData.properties" :key="item">-->
                <!--                    <span style="margin-right: 8px">{{ (nodeObjMap[key] ? nodeObjMap[key] : key) + ':' }}</span>-->
                <!--                    <span style="text-align: right"-->
                <!--                        ><b>{{ item }}</b></span-->
                <!--                    >-->
                <!--                </div>-->
                <CompanyCard :node-data="selectNodeData" v-if="selectNodeData.label === 'company'"></CompanyCard>
                <ProductCard :node-data="selectNodeData" v-else-if="selectNodeData.label === 'product'"></ProductCard>
                <HoldCompanyCard :node-data="selectNodeData" v-else-if="selectNodeData.label === 'holdCompany'"></HoldCompanyCard>
                <IndustryCard :node-data="selectNodeData" v-else-if="selectNodeData.label"></IndustryCard>
            </el-card>
        </div>
    </div>
</template>

<script>
import ForceGraph3D from '3d-force-graph';
// threejs的精灵标签，用于文字的展示
import SpriteText from 'three-spritetext';
import CompanyCard from '@/page/D2Page/components/CompanyCard.vue';
import ProductCard from '@/page/D2Page/components/ProductCard.vue';
import HoldCompanyCard from '@/page/D2Page/components/HoldCompanyCard.vue';
import IndustryCard from '@/page/D2Page/components/IndustryCard.vue';

export default {
    name: 'threeGraph',
    components: { IndustryCard, HoldCompanyCard, ProductCard, CompanyCard },
    props: {
        names: {
            type: Array
        },
        labels: Array,
        linkTypes: Array
    },
    mounted() {
        this.threeInit();
        this.$bus.$on('refresh3dGraph', () => {
            this.threeInit();
        });
    },
    data() {
        return {
            // ForceGraph3D对象，供全局调用，实现动态更新
            Graph: {},
            // threeRender()最终展示到页面上的数据（节点隐藏功能）
            graphData: {
                nodes: [],
                links: []
            },
            // 图例的名称、对应的颜色以及图例状态
            states: [],
            nodeColors: ['#65d538', '#aaaaff', '#0e83d2', '#ec2721', '#FFC0CB', '#BA55D3', '#1E90FF', '#7FFFD4', '#FFFF00'],
            selectNodeData: {}, // 选中节点的详细信息展示
            temp: {}, // 临时存储编辑时的节点信息
            dialogFormVisible: false,
            isEdit: true,
            // 节点属性对应的标签名称
            nodeObjMap: {
                code: '代码',
                fullname: '公司全称',
                location: '上市位置',
                name: '公司简称',
                time: '创建时间'
            },
            width: 0,
            height: 0
        };
    },
    watch: {
        // 当请求到新的数据时，重新渲染
        data(newData, oldData) {
            console.log(newData, oldData);
            this.threeInit();
        }
    },
    methods: {
        // 视图更新
        update() {
            var svgDom = document.getElementById('3d-graph');
            svgDom.innerHTML = '';
            svgDom.width = this.width;
            svgDom.height = this.height;
            this.threeRender();
        },
        // 编辑当前选中节点
        btnEdit() {
            this.temp = Object.assign({}, this.selectNodeData.properties); // copy obj
            this.dialogFormVisible = true;
            console.log(this.selectNodeData);
        },
        doEdit() {
            // console.log(this.data)
            let i = 0;
            // 更新props的data 和 selectNodeData
            this.selectNodeData.name = this.temp.name;
            this.selectNodeData.properties = this.temp;
            for (let node of this.data.nodes) {
                // console.log(node.id === this.selectNodeData.id)
                // console.log(node.id)
                // console.log(this.selectNodeData.id)
                if (node.id == this.selectNodeData.id) {
                    // this.$set(this.data.nodes, i, this.selectNodeData)
                    // this.$set(this.nodes, i, this.selectNodeData)
                    this.data.nodes[i].properties = this.temp;
                    this.nodes[i].properties = this.temp;
                    break;
                }
                i++;
            }
            this.dialogFormVisible = false;
            this.threeInit();
            this.$message({
                message: '更新成功',
                type: 'success'
            });
        },
        cancelEdit() {
            this.dialogFormVisible = false;
        },
        // d3初始化，包括数据解析、数据渲染
        threeInit() {
            this.graphData.links = this.$store.state.graphData.links;
            this.graphData.nodes = this.$store.state.graphData.node;
            this.width = this.$refs.d3Container.offsetWidth;
            this.height = this.$refs.d3Container.offsetHeight;
            console.log('d3 data', this.links, this.nodes);
            console.log('canvas', this.width, this.height);
            this.threeRender();
            // 数据状态初始化
            this.stateInit();
        },
        // 数据状态初始化
        stateInit() {
            this.states = Array(this.names.length).fill('on');
        },
        threeRender() {
            // DOM初始化及数据挂载
            const elm = document.getElementById('3d-graph');
            this.Graph = ForceGraph3D()(elm).graphData(this.graphData);
            // 设置画布样式、节点及关系样式、事件绑定等
            this.Graph.height(this.height)
                .width(this.width)
                .backgroundColor('#ffffff')
                // 节点样式和标签设置
                .nodeRelSize(12)
                .nodeColor((node) => {
                    let index = 0;
                    switch (node.label) {
                        case this.labels[0]:
                            break;
                        case this.labels[1]:
                            index = 1;
                            break;
                        case this.labels[2]:
                            index = 2;
                            break;
                        default:
                            index = 3;
                            break;
                    }
                    return this.nodeColors[index];
                })
                // .nodeAutoColorBy('label')
                // 给节点添加文字
                // .nodeThreeObjectExtend(true)
                .nodeThreeObject((node) => {
                    const sprite = new SpriteText(node.properties.name);
                    sprite.material.depthWrite = false; // make sprite background transparent
                    // 设置文字颜色
                    let i = 0;
                    // switch(node.label) {
                    //   case this.labels[0]: break;
                    //   case this.labels[1]: index = 1;break;
                    //   case this.labels[2]: index = 2;break;
                    //   default: index = 3;break;
                    // }
                    for (; i < this.labels.length; i++) {
                        if (node.label === this.labels[i]) break;
                    }
                    sprite.color = this.nodeColors[i];
                    sprite.textHeight = 14;
                    return sprite;
                })
                .nodeThreeObjectExtend(true)
                .nodeLabel((node) => `${node.label}: ${node.properties.name}`)
                .nodeOpacity(0.8)
                // 节点事件绑定
                .onNodeHover((node) => (elm.style.cursor = node ? 'pointer' : null))
                .onNodeClick((node) => {
                    console.log(node);
                    //设置#info h4样式的颜色为该节点的颜色，文本为该节点name
                    this.$set(this.selectNodeData, 'id', node.id);
                    this.$set(this.selectNodeData, 'name', node.properties.name);
                    this.$set(this.selectNodeData, 'label', node.label);
                    this.$set(this.selectNodeData, 'properties', node.properties);
                    // 获取节点类型对应的颜色
                    // let index = 0
                    // switch(node.label) {
                    //   case 'Enterprise': break;
                    //   case 'Type': index = 1;break;
                    //   case 'Region': index = 2;break;
                    //   default: index = 3;break;
                    // }
                    let i = 0;
                    for (; i < this.labels.length; i++) {
                        if (node.label === this.labels[i]) break;
                    }
                    this.$set(this.selectNodeData, 'color', this.nodeColors[i]);
                    this.$set(this.selectNodeData, 'properties', node.properties);
                })
                .linkColor('#3989fa')
                .linkColor((link) => {
                    let index = 0;
                    const colors = ['#faa'];
                    switch (link.type) {
                        case 'export':
                            break;
                        case 'zhuyingchanpin':
                            index = 1;
                            break;
                        case 'chanpingxiaolei':
                            index = 2;
                            break;
                        default:
                            index = 3;
                            break;
                    }
                    return this.nodeColors[index];
                })
                .linkOpacity(1);

            // Spread nodes a little wider
            this.Graph.d3Force('charge').strength(-2000);
        },
        threeUpdate() {
            let data = this.$store.state.graphData;
            this.Graph.graphData({
                data
            });
        }
    }
};
</script>

<style lang="scss" scoped>
@media only screen and (max-width: 1500px) {
    #info,
    #indicator {
        display: none !important;
    }
}

#indicator {
    position: absolute;
    // left: 50px;
    // bottom: 30px;
    left: 3vw;
    bottom: 2vw;
    text-align: left;
    color: #f2f2f2;
    font-size: 14px;
    font-weight: bold;

    & > div {
        margin-bottom: 4px;
    }

    span {
        display: inline-block;
        width: 32px;
        height: 16px;
        position: relative;
        top: 2px;
        margin-right: 8px;
    }
}

/*悬浮节点的info样式*/
/*悬浮节点的info样式*/
#info {
    position: absolute;
    bottom: 0px;
    right: 0px;
    width: 300px;
    .node-card {
        text-align: left;
        // transition: background-color;
        // transition-delay: .3s;
        // transition-timing-function: ease;
        .el-card__header {
            border-bottom: 1px solid #50596d;
        }
    }
}

canvas {
    border: 1px solid;
}
.three-graph {
    height: 100%;
}
.d3graph-container {
    height: 100%;
}
</style>
